#include "tcpmgr.h"
#include<usermgr.h>


TcpMgr::TcpMgr():_host(""),_port(0),_b_recv_pedding(false),_message_id(0),_message_len(0)
{
    QObject::connect(&_socket,&QTcpSocket::connected,[&](){
        qDebug()<<"connect to server......";
        emit sig_con_success(true);
    });

    QObject::connect(&_socket,&QTcpSocket::readyRead,[&](){
        _buffer.append(_socket.readAll());
        QDataStream stream(&_buffer,QIODevice::ReadOnly);
        stream.setVersion(QDataStream::Qt_5_0);
        forever{
            //头部数据未处理完
            if(!_b_recv_pedding){
                //获取到长度不如头部长度
                if(_buffer.size()<static_cast<int>(sizeof(quint16)*2)){
                    return;
                }
                //长度大于或等于头部长度
                stream>>_message_id>>_message_len;
                //将头部长度去掉
                _buffer=_buffer.mid(sizeof(quint16)*2);
                qDebug()<<"message i1d is: "<<_message_id;
                qDebug()<<"message l1en is: "<<_message_len;

            }
            //剩余长度不足数据本体长度
            if(_buffer.size()<_message_len){
                _b_recv_pedding=true;
                qDebug()<<"123";
                return;
            }
            //剩余长度满足数据长度
            _b_recv_pedding=false;
            QByteArray message_body=_buffer.mid(0,_message_len);
            qDebug()<<"recvive body message is: "<<message_body;
            _buffer=_buffer.mid(_message_len);
            handleMsg(ReqId(_message_id),_message_len,message_body);
            // return;
        }
    });

    QObject::connect(&_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::errorOccurred), [&](QAbstractSocket::SocketError socketError) {
        qDebug()<<"Error: "<<_socket.errorString();
        switch(socketError){
        case QTcpSocket::ConnectionRefusedError:
            qDebug() << "Connection Refused!";
            emit sig_con_success(false);
            break;
        case QTcpSocket::RemoteHostClosedError:
            qDebug() << "Remote Host Closed Connection!";
            break;
        case QTcpSocket::HostNotFoundError:
            qDebug() << "Host Not Found!";
            emit sig_con_success(false);
            break;
        case QTcpSocket::SocketTimeoutError:
            qDebug() << "Connection Timeout!";
            emit sig_con_success(false);
            break;
        case QTcpSocket::NetworkError:
            qDebug() << "Network Error!";
            break;
        default:
            qDebug() << "Other Error!";
            break;
        }

    });
    QObject::connect(&_socket,&QTcpSocket::disconnected,[&](){
        qDebug()<<"disConnect from server";

    });

    QObject::connect(this,&TcpMgr::sig_send_data,&TcpMgr::slot_send_data);

    initHandlers();
}

void TcpMgr::initHandlers()
{
    _handlers.insert(ID_CHAT_LOGIN_RSP,[this](ReqId id,int len ,QByteArray data){
        qDebug()<<"handle id is: "<<id<<" data is: "<<data;
        QJsonDocument jsonDoc =QJsonDocument::fromJson(data);
        if(jsonDoc.isNull()){
            qDebug()<<"fail to create jsonDoc";
            return;
        }
        QJsonObject jsonObj=jsonDoc.object();
        if(!jsonObj.contains("error")){
            int err=ErrorCodes::ERR_JSON;
            qDebug()<<"login failed,err is json parse err: "<<err;
            emit sig_login_failed(err);
            return;

        }
        int err=jsonObj["error"].toInt();
        if(err!=ErrorCodes::SUCCESS){
            qDebug()<<"login failed,err is: "<<err;
            emit sig_login_failed(err);
            return;
        }
        auto uid=jsonObj["uid"].toInt();
        auto name = jsonObj["name"].toString();
        auto nick = jsonObj["nick"].toString();
        auto icon = jsonObj["icon"].toString();
        auto sex = jsonObj["sex"].toInt();
        auto user_info=std::make_shared<UserInfo>(uid,name,nick,icon,sex);
        UserMgr::GetInstance()->SetUserInfo(user_info);
        //修正
        UserMgr::GetInstance()->setUid(uid);
        UserMgr::GetInstance()->setToken(jsonObj["token"].toString());
        //
        if(jsonObj.contains("apply_list")){
            UserMgr::GetInstance()->AppendApplyList(jsonObj["apply_list"].toArray());
            qDebug()<<"have apply_list";
        }
        //添加好友列表
        if(jsonObj.contains("friend_list")){
            UserMgr::GetInstance()->AppendFriendList(jsonObj["friend_list"].toArray());
            qDebug()<<"have friend_list";
        }
        qDebug()<<"login success----------------------------";

        emit sig_swich_chatdlg();
    });

    _handlers.insert(ID_SEARCH_USER_RSP,[this](ReqId id,int len ,QByteArray data){
        Q_UNUSED(len);
        qDebug()<<"handle id is: "<<id<<" data is: "<<data;
        QJsonDocument jsonDoc =QJsonDocument::fromJson(data);
        if(jsonDoc.isNull()){
            qDebug()<<"fail to create jsonDoc";
            return;
        }
        QJsonObject jsonObj=jsonDoc.object();
        if(!jsonObj.contains("error")){
            int err=ErrorCodes::ERR_JSON;
            qDebug()<<"search failed,err is json parse err: "<<err;
            emit sig_user_search(nullptr);
            return;

        }
        int err=jsonObj["error"].toInt();
        if(err!=ErrorCodes::SUCCESS){
            qDebug()<<"--search failed,err is: "<<err;
            emit sig_user_search(nullptr);
            return;
        }
        auto search_info=std::make_shared<SearchInfo>(jsonObj["uid"].toInt(),jsonObj["name"].toString(),
                                                        jsonObj["nick"].toString(),jsonObj["desc"].toString(),
                                                        jsonObj["sex"].toInt(),jsonObj["icon"].toString());
        qDebug()<<"search success----------------------------";
        emit sig_user_search(search_info);
    });


    _handlers.insert(ID_ADD_FRIEND_RSP,[this](ReqId id,int len ,QByteArray data){
        Q_UNUSED(len);
        qDebug()<<"handle id is: "<<id<<" data is: "<<data;
        QJsonDocument jsonDoc =QJsonDocument::fromJson(data);
        if(jsonDoc.isNull()){
            qDebug()<<"fail to create jsonDoc";
            return;
        }
        QJsonObject jsonObj=jsonDoc.object();
        if(!jsonObj.contains("error")){
            int err=ErrorCodes::ERR_JSON;
            qDebug()<<"Add failed,err is json parse err: "<<err;
            return;

        }
        int err=jsonObj["error"].toInt();
        if(err!=ErrorCodes::SUCCESS){
            qDebug()<<"--add friend failed,err is: "<<err;
            return;
        }

        qDebug()<<"Addfriend rsp success----------------------------";
    });

    _handlers.insert(ID_NOTIFY_ADD_FRIEND_REQ, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        // 检查转换是否成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        if (!jsonObj.contains("error")) {
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "notify add friend Failed, err is Json Parse Err" << err;
            emit sig_user_search(nullptr);
            return;
        }
        int err = jsonObj["error"].toInt();
        if (err != ErrorCodes::SUCCESS) {
            qDebug() << "Login Failed, err is " << err;
            emit sig_user_search(nullptr);
            return;
        }
        int from_uid = jsonObj["applyuid"].toInt();
        QString name = jsonObj["name"].toString();
        QString desc = jsonObj["desc"].toString();
        QString icon = jsonObj["icon"].toString();
        QString nick = jsonObj["nick"].toString();
        int sex = jsonObj["sex"].toInt();
        auto apply_info = std::make_shared<AddFriendApply>(
            from_uid, name, desc,
            icon, nick, sex);
        emit sig_friend_apply(apply_info);
    });

    //对端认证后发回的信息
    _handlers.insert(ID_NOTIFY_AUTH_FRIEND_REQ, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        // 检查转换是否成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        if (!jsonObj.contains("error")) {
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "notify auth friend Failed, err is Json Parse Err" << err;
            return;
        }
        int err = jsonObj["error"].toInt();
        if (err != ErrorCodes::SUCCESS) {
            qDebug() << "notify auth friend Failed, err is " << err;
            return;
        }
        int from_uid = jsonObj["fromuid"].toInt();
        QString name = jsonObj["name"].toString();
        QString icon = jsonObj["icon"].toString();
        QString nick = jsonObj["nick"].toString();
        int sex = jsonObj["sex"].toInt();

        auto auth_info=std::make_shared<AuthInfo>(from_uid,name,nick,icon,sex);

        emit sig_add_auth_friend(auth_info);
    });


    //自己点击认证后发回的信息
    _handlers.insert(ID_AUTH_FRIEND_RSP, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        // 检查转换是否成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        if (!jsonObj.contains("error")) {
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "auth friend Failed, err is Json Parse Err" << err;
            return;
        }
        int err = jsonObj["error"].toInt();
        if (err != ErrorCodes::SUCCESS) {
            qDebug() << "auth friend Failed, err is " << err;
            return;
        }

        auto name = jsonObj["name"].toString();
        auto nick = jsonObj["nick"].toString();
        auto icon = jsonObj["icon"].toString();
        auto sex = jsonObj["sex"].toInt();
        auto uid = jsonObj["uid"].toInt();
        auto rsp=std::make_shared<AuthRsp>(uid,name,nick,icon,sex);
        emit sig_auth_rsp(rsp);

        qDebug()<<"auth friend success";
    });

    //发送消息后发回的信息
    _handlers.insert(ID_TEXT_CHAT_MSG_RSP, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        // 检查转换是否成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        if (!jsonObj.contains("error")) {
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "chat msg rsp Failed, err is Json Parse Err" << err;
            return;
        }
        int err = jsonObj["error"].toInt();
        if (err != ErrorCodes::SUCCESS) {
            qDebug() << "chat msg rsp Failed, err is " << err;
            return;
        }

        qDebug()<<"chat msg rsp success";
    });

    //对方发送消息自己收到的信息
    _handlers.insert(ID_NOTIFY_TEXT_CHAT_MSG_REQ, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        // 检查转换是否成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        if (!jsonObj.contains("error")) {
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "text chat req Failed, err is Json Parse Err" << err;
            return;
        }
        int err = jsonObj["error"].toInt();
        if (err != ErrorCodes::SUCCESS) {
            qDebug() << "text chat req Failed, err is " << err;
            return;
        }
        qDebug()<<"text chat req success";
        auto msg_ptr=std::make_shared<TextChatMsg>(jsonObj["fromuid"].toInt(),
                                                     jsonObj["touid"].toInt(),
                                                     jsonObj["text_array"].toArray());

        emit sig_text_chat_msg(msg_ptr);
    });
}

void TcpMgr::handleMsg(ReqId id, int len, QByteArray data)
{
    auto iter=_handlers.find(id);
    if(iter==_handlers.end()){
        qDebug()<<"not found id ["<<id<<"]";
        return;
    }
    iter.value()(id,len,data);
}

void TcpMgr::slot_tcp_connect(ServerInfo server)
{
    qDebug()<<"recvive tcp connect signal";
    qDebug()<<"connect to server.....";
    _host=server.Host;
    _port=static_cast<uint16_t>(server.Port.toUInt());
    _socket.connectToHost(_host,_port);
}

void TcpMgr::slot_send_data(ReqId reqId, QByteArray dataBytes)
{
    uint16_t id=reqId;
    quint16 len=static_cast<quint16>(dataBytes.size());
    QByteArray block;
    QDataStream stream(&block,QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::BigEndian);
    stream<<id<<len;
    block.append(dataBytes);
    _socket.write(block);
}
